(() => {
  // 布尔值
  let isDone: boolean = false
  isDone = true
  // isDone = 'abc'  // error
  // 数值
  let age: number
  age = 18
  // age = '4' // error
  // 字符串
  let info:string = `我今年${age}岁`
  // info = 3  // error

  // undefined 和 null   都只有一个值   一般不会单独使用
  let u: undefined = undefined
  // u = 'abc' // error
  // u =null  // error
  let n: null = null
  // n = undefined //  error

  // 数组
  let arr: string[] = ['abc'/* , 12 */]
  let arr2: Array<number> = [2, 3.2/* , '2' */]

  // 元组 Tuple: 指定了元素类型和个数的数组
  let tuples: [string, number] = ['tom', 23]
  // tuples = ['jack', '24']  // error

  /* 
  枚举: 可以为一组互异的数值或字符串赋予友好的名字
    本质是: 对象
  */
  enum Color {
    Red=1, Green, Blue
  }
  console.log(Color)

  const cat = {
    name: 'tom',
    color: 1
  }

  switch (cat.color) {
    case Color.Red:
      console.log('猫的颜色是红色')
      break;
    case Color.Green:
      console.log('猫的颜色是绿色')
      break;
    case Color.Blue:
      console.log('猫的颜色是蓝色')
      break;
    default:
      console.log('猫的颜色是其它颜色')
  }

  // 利用枚举对多个字符串路径进行统一存储
  enum ApiPath {
    Login = '/admin/login',
    Logout = '/admin/logout',
    GetInfo = '/admin/userinfo'
  }
  console.log(ApiPath)

  // axios.post(ApiPath.Login)

  // any: 任意类型  可以存储任意类型的值
  let a: any = 3
  a = 'abc'
  a = {}
  let arr3: any[] = ['abc', 2, () => {}]

  // void 常用来指定函数没有返回值
  function fn(): void {
    // return null // error
    // 不返回或返回undefined可以
    return undefined 
  }

  // object
  function fn2(): object {
    // return null // error
    // return undefined  // error
    // return {}
    // return []
    // return () => {}
    return new Number(2)
  }

  // 联合类型
  let sn: string|number = 'abc'
  sn = 3
  // sn = true // error
  let sn2: string|null = null
  sn2 = 'abc'
  sn2 = null
  // sn2 = 3 // error
  /* 需求1: 定义一个一个函数得到一个数字或字符串值的字符串形式值 */
  function getString(value: number|string) {
    return value.toString()
  }
  getString(123) // '123'
  getString('abc') // 'abc'

  /* 需求2: 定义一个一个函数得到一个数字或字符串值的长度 */
  function getLength(value: number|string) {
    // return value.length  // error
    return value.toString().length
  }
  getLength('abc')
  getLength(123)

  /* 
  类型断言: 我们告诉ts编译器将变量精武看作我们指定的类型
  */
  function getLength2(value: number|string) {
    if ((<string>value).length) {
      return (value as string).length
    } else {
      return value.toString().length
    }
  }

  /* 
  类型推断: ts编译根据定义变量指定的初始值来指定类型, 如果没有指定初始值, 推断any类型
  */
  let aa = 3
  // aa = 'abc' // error
  let aa2 // 推断为any类型
  aa2 = 4
  aa2 = 'abc'


})()